home *** CD-ROM | disk | FTP | other *** search
/ The Utilities Experience / The Utilities Experience - Volume 1.iso / software / comms / thor_2.22 / thor.lha / rexx / UUDecode.thor < prev    next >
Text File  |  1995-12-18  |  15KB  |  523 lines

  1. /*
  2. ** $VER: UUDecode.thor 4.1 (13.11.95)
  3. ** by Troels Walsted Hansen <troels@stud.cs.uit.no>
  4. **
  5. ** Run CfgUUDecode.thor to configure this script.
  6. */
  7.  
  8. options results
  9. options failat 31    /* otherwise the output window may pop up all the time */
  10.  
  11. signal on break_c
  12. signal on halt
  13. signal on syntax
  14.  
  15. /* Initialize some variables */
  16.  
  17. fromthor = 0; cmdlinemode = 0; cfgfile  =  "";  tmpdir  =  ""; destdir = ""; uudecoder= ""; uuprogpath = ""
  18. filenotes = 0; filerecog = 0; filetypecount = 0; progwin = 0; nocurrentmsg = 0; uudecoder.count = 0; firsttime = 0
  19.  
  20. /* Find THOR and BBSREAD ARexx ports' */
  21.  
  22. if(pos('THOR.', address()) > 0) then fromthor = 1
  23. p=address()||' '||show('P',,);if pos('THOR.',p)>0 then thorport=word(substr(p,pos('THOR.',p)),1);else do;say 'No THOR port found!';exit(0);end
  24. if ~show('p', 'BBSREAD') then do; address command; "run >nil: `GetEnv THOR/THORPath`bin/LoadBBSRead"; "WaitForPort BBSREAD"; end
  25.  
  26. address(thorport)
  27.  
  28. /* Get the path of the configuration file */
  29.  
  30. call open(pn, 'ENV:Thor/THORPATH', 'R')
  31. thorpath = readln(pn)
  32. call close(pn)
  33.  
  34. if ~exists(thorpath'rexx') then cfgfile = 'ENV:Thor/UUDecode.cfg'
  35. else
  36. do
  37.     if exists(thorpath'rexx/UUDecode.cfg') then cfgfile = thorpath'rexx/UUDecode.cfg'
  38.     else cfgfile = 'ENV:Thor/UUDecode.cfg'
  39. end
  40.  
  41. if ~exists(cfgfile) then
  42. do
  43.     REQUESTNOTIFY '"Couldn''t find config file ('cfgfile').\nPlease run CfgUUDecode.thor and try again."' '"_Configure now|_Abort"'
  44.     if(result) then address command 'run <>nil: rx ' || thorpath || 'Rexx/CfgUUDecode.thor'
  45.     signal cleanup
  46. end
  47.  
  48. /* Read configuration */
  49.  
  50. call readcfg
  51.  
  52. /* If this is the first time the script is run, we ask the user to run the configscript */
  53.  
  54. if(firsttime) then
  55. do
  56.     address(thorport)
  57.     REQUESTNOTIFY TEXT '"It seems that you''re running this script for\nthe first time. It is very likely that you\nneed to change some of the defaults for this\nscript to work. Press Configure to configure\nthis script now, or Abort to quit the script."' BT '"_Configure|_Abort"'
  58.     if(result) then address command 'run <>nil: rx ' || thorpath || 'Rexx/CfgUUDecode.thor'
  59.     signal cleanup
  60. end
  61.  
  62. /* General tmpfile */
  63.  
  64. tmpfile = tmpdir || 'doscommand.output'
  65.  
  66. /*  Disable filenoteadding if we got a filename on the commandline
  67.  *  and got started from somewhere other than THOR
  68.  */
  69.  
  70. parse arg msgfilename
  71. if(msgfilename ~= '') then
  72. do
  73.     cmdlinemode = 1
  74.     if(fromthor ~= 1) then filenotes = 0
  75. end
  76. else msgfilename = tmpdir || 'Message.uu'
  77.  
  78. if(~cmdlinemode) then
  79. do
  80.     /* lock the gui till we're done */
  81.  
  82.     address(thorport)
  83.     LOCKGUI
  84.  
  85.     /* Need this info no matter what... */
  86.  
  87.     CURRENTMSG stem MSG
  88.     if(rc ~= 0) then
  89.     do
  90.         nocurrentmsg = 1
  91.  
  92.         CURRENTSYSTEM stem MSG
  93.         if(rc ~= 0) then
  94.         do
  95.             REQUESTNOTIFY TEXT '"CURRENTSYSTEM:\n'THOR.LASTERROR'"' BT '"_Abort"'
  96.             signal cleanup
  97.         end
  98.     end
  99.  
  100.     /* find out whether multiple messages has been selected */
  101.     address(thorport)
  102.     GETMSGLISTSELECTED stem SELECTED
  103.     myrc = rc
  104.  
  105.     if(myrc = 0 & SELECTED.COUNT > 0 & nocurrentmsg ~= 1) then /* yes, there are multiple msgs, now query user */
  106.     do
  107.         REQUESTNOTIFY TEXT '"UUDecode all files contained\nin all selected messages?"' BT '"_Yes|_Only current|_Abort"'
  108.  
  109.         if(result = 1) then nocurrentmsg = 1
  110.         else if(result = 2) then SELECTED.COUNT = 0
  111.         else signal cleanup
  112.     end
  113.  
  114.     if((SELECTED.COUNT = 0 | (myrc > 1 & myrc < 6)) & MSG.MSGNR ~= "MSG.MSGNR") then /* save current msg only */
  115.     do
  116.         SELECTED.COUNT = 1
  117.         SELECTED.1 = MSG.MSGNR
  118.  
  119.         /* Get the name or email address of the sender of this message */
  120.         if(filenotes) then
  121.         do
  122.             address(bbsread)
  123.             READBRMESSAGE BBSNAME '"'MSG.BBSNAME'"' CONFNAME '"'MSG.CONFNAME'"' MSGNR MSG.MSGNR headstem HEADTAGS
  124.             if(rc ~= 0) then
  125.             do
  126.                     address(thorport)
  127.                     REQUESTNOTIFY TEXT '"READBRMESSAGE:\n'BBSREAD.LASTERROR'"' BT '"_Abort"'
  128.                     signal cleanup
  129.             end
  130.             if(HEADTAGS.FROMADDR ~= 'HEADTAGS.FROMADDR') then MSG.SENDER = HEADTAGS.FROMADDR
  131.             else MSG.SENDER = HEADTAGS.FROMNAME
  132.         end
  133.     end
  134.  
  135.     if(myrc > 5 | SELECTED.COUNT = 0) then signal cleanup /* fatal error */
  136.  
  137.     /* Open progressbar */
  138.  
  139.     address(thorport)
  140.     OPENPROGRESS TITLE '"UUDecoding message(s)..."' TOTAL SELECTED.COUNT AT "_Abort" PROGRESSCHARWIDTH 38
  141.     if rc = 0 then progwin = result
  142.     else 
  143.     do
  144.         REQUESTNOTIFY '"OPENPROGRESS:\n'THOR.LASTERROR'"' '"_Abort"'
  145.         signal cleanup
  146.     end
  147.  
  148.     /* Save msg(s) to disk with progressbar */
  149.  
  150.     do i=1 to SELECTED.COUNT
  151.         UPDATEPROGRESS REQ progwin CURRENT i PROGRESSTEXT '"' || 'Saving message ' || i ' of ' || SELECTED.COUNT || ' to disk...' || '"'
  152.         if(rc ~= 0) then signal cleanup
  153.  
  154.         SAVEMESSAGE BBSNAME '"'MSG.BBSNAME'"' CONFNAME '"'MSG.CONFNAME'"' MSGNR SELECTED.i FILENAME msgfilename NOHEADER NOANSI
  155.         if(rc ~= 0) then
  156.         do
  157.             REQUESTNOTIFY TEXT '"SAVEMESSAGE:\n'THOR.LASTERROR'"' BT '"_Abort'
  158.             signal cleanup
  159.         end
  160.     end
  161. end
  162. else if ~exists(msgfilename) then
  163. do
  164.     address(thorport)
  165.     REQUESTNOTIFY TEXT '"Message containing uuencoded file not found."' BT '"_Ok"'
  166.     signal cleanup
  167. end
  168.  
  169. /* extract filenames if filenotes and/or filerecog is enabled */
  170.  
  171. if(filenotes | filerecog) then call FindFileNames
  172.  
  173. /* uuDecode all files contained in the tempfile */
  174.  
  175. founduu = 0
  176.  
  177. do i=1 to uudecoder.count
  178.     if(upper(uudecoder) = upper(uudecoder.i.shortname)) then 
  179.     do
  180.         founduu = 1
  181.         cmd = uudecoder.i.commandline
  182.  
  183.         cmd = substitute(cmd, '%TmpFile', tmpfile)
  184.         cmd = substitute(cmd, '%MsgFilename', msgfilename)
  185.         cmd = substitute(cmd, '%DestDir', destdir)
  186.     end
  187. end
  188.  
  189. if(~founduu) then
  190. do
  191.     address(thorport)
  192.     REQUESTNOTIFY TEXT '"UUDecoder not configured correctly."' BT '"_Configure|_Abort"'
  193.     if(result) then address command 'run <>nil: rx 'thorpath'Rexx/CfgUUDecode.thor'
  194.     signal cleanup
  195. end
  196.  
  197. if(~cmdlinemode) then
  198. do
  199.     address(thorport)
  200.     UPDATEPROGRESS REQ progwin PROGRESSTEXT '"UUDecoding file(s)..."'
  201. end
  202.  
  203. address command cmd
  204. if(rc ~= 0) then
  205. do
  206.     call open(tmpfh, tmpfile, R)
  207.     errormsg = ''
  208.  
  209.     do until eof(tmpfh)
  210.         errormsg = errormsg || '\n' || readln(tmpfh)
  211.     end
  212.  
  213.     call close(tmpfh)
  214.  
  215.     errormsg = 'UUDecoding did not succeed.' || left(errormsg, length(errormsg)-2)
  216.  
  217.     address(thorport)
  218.     REQUESTNOTIFY TEXT '"'errormsg'"' BT '"_Configure|_Abort"'
  219.     if(result) then address command 'run <>nil: rx 'thorpath'Rexx/CfgUUDecode.thor'
  220.     signal cleanup
  221. end
  222.  
  223. /* Add filenotes if that option is switched on */
  224.  
  225. if(filenotes) then
  226. do
  227.     if(~cmdlinemode) then
  228.     do
  229.         address(thorport)
  230.         UPDATEPROGRESS REQ progwin PROGRESSTEXT '"Adding filenote(s)..."'
  231.     end
  232.  
  233.     if(nocurrentmsg) then str = 'From ' || MSG.CONFNAME || ' on ' || MSG.BBSNAME
  234.     else str = 'From ' || MSG.SENDER || ' in ' || MSG.CONFNAME || ' on ' || MSG.BBSNAME
  235.  
  236.     do i=1 to (filenamecount-1)
  237.         address command 'filenote <>nil: ' || '"' || destdir || realfilename.i || '"' || ' ' || '"' || str || '"' || ' QUIET'
  238.     end
  239. end
  240.  
  241. /* Match fileextension against those configured by the user
  242.    if filetyperecognition is switched on. */
  243.  
  244. if(filerecog) then
  245. do
  246.     if(~cmdlinemode) then
  247.     do
  248.         address(thorport)
  249.         UPDATEPROGRESS REQ progwin PROGRESSTEXT '"Doing filetype recognition..."'
  250.     end
  251.  
  252.     address(thorport)
  253.     GETGLOBALCONFIG stem THORCONFIG
  254.     if(rc ~= 0) then
  255.     do
  256.         REQUESTNOTIFY TEXT '"GETGLOBALCONFIG:\n'THOR.LASTERROR'"' BT '"_Abort"'
  257.         signal cleanup
  258.     end
  259.  
  260.     do i=1 to (filenamecount-1)
  261.         thisext = upper(substr(realfilename.i, lastpos(".", realfilename.i)+1))
  262.  
  263.         do j=1 to filetypecount
  264.             if(pos(thisext, filetype.j.ext) > 0 | upper(filetype.j.ext) = 'ALL') then
  265.             do
  266.                 /* build a list of choices to present to the user */
  267.  
  268.                 choices = ''
  269.  
  270.                 do k=1 to filetype.j.actioncount
  271.                     choices = choices || '|' || filetype.j.actionname.k
  272.                 end
  273.  
  274.                 choices = substr(choices, 2) || '|_Skip this one'
  275.  
  276.                 /* ask the user what to do */
  277.  
  278.                 address(thorport)
  279.                 REQUESTNOTIFY TEXT '"' || 'The file ' || realfilename.i || ' has been recognized as ' || filetype.j.name || '.\nWhich action would you like to perform on it?' || '"' BT '"'choices'"'
  280.                 action = result
  281.  
  282.                 if(action ~= 0) then
  283.                 do
  284.                     /* substitute internal vars with actual meaning */
  285.                     cmd = substitute(filetype.j.actioncmdl.action, '%FileName', destdir || realfilename.i)
  286.                     cmd = substitute(cmd, '%ThorScreen', THORCONFIG.PUBSCREENNAME)
  287.                     cmd = substitute(cmd, '%RequestDir')
  288.                     cmd = substitute(cmd, '%RequestFile')
  289.  
  290.                     /* change the default output window to my very own */
  291.                     call close 'STDOUT'
  292.                     call close 'STDIN'
  293.                     call open 'STDOUT','CON:0/16//400/UUDecode.thor/CLOSE/AUTO/WAIT/SCREEN' || THORCONFIG.PUBSCREENNAME
  294.                     call pragma '*','STDOUT'
  295.                     call open 'STDIN','*'
  296.  
  297.                     /* launch the internal/external action */
  298.                     command = upper(word(cmd, 1))
  299.                     if(command = 'SHOWPICTURE' | command = 'SHOWTEXT') then
  300.                     do
  301.                         address(thorport)
  302.                         interpret cmd
  303.                     end
  304.                     else address command cmd
  305.                     if(rc ~= 0) then
  306.                     do
  307.                         address(thorport)
  308.                         REQUESTNOTIFY TEXT '"' || 'Failed to launch your configured\ncommandline for ' || filetype.j.actionname.action || '.' || '"' BT '"_Configure|_Ok"'
  309.                         if(result) then address command 'run <>nil: rx 'thorpath'Rexx/CfgUUDecode.thor'
  310.                     end
  311.                 end
  312.             end
  313.         end
  314.     end
  315. end
  316.  
  317. /* end of the script */
  318.  
  319. signal cleanup
  320.  
  321. /* Some experimental error detection stuff */
  322.  
  323. error:
  324. syntax:
  325. say '+++Error 'rc' in line 'sigl': 'errortext(rc)
  326. say sourceline(sigl)
  327. if THOR.LASTERROR ~= 'THOR.LASTERROR' then say THOR.LASTERROR
  328. if BBSREAD.LASTERROR ~= 'BBSREAD.LASTERROR' then say BBSREAD.LASTERROR
  329.  
  330. break_c:
  331. halt:
  332. cleanup:
  333.  
  334. /* delete tmpfiles used */
  335.  
  336. if(exists(msgfilename) & ~cmdlinemode) then address command 'delete ' || msgfilename || ' quiet'
  337. if(exists(tmpfile)) then address command 'delete ' || tmpfile || ' quiet'
  338.  
  339. /* Close progressbar if open */
  340.  
  341. if progwin ~= 0 then if progwin ~= 'PROGWIN' then
  342. do
  343.     address(thorport)
  344.     CLOSEPROGRESS REQ progwin
  345.     progwin = 0
  346. end
  347.  
  348. UNLOCKGUI
  349.  
  350. exit(0)
  351.  
  352. /******************************************************************************
  353. ********************************** PROCEDURES *********************************
  354. ******************************************************************************/
  355.  
  356. /********************** Open and read configuration file *********************/
  357.  
  358. readcfg: procedure expose cfgfile tmpdir destdir uudecoder uuprogpath filenotes filerecog filetypecount filetype. progwin globalcfg. thorport uudecoder. firsttime
  359.  
  360. call open(cf, cfgfile, 'R')
  361.  
  362. do until eof(cf)
  363. subentry = ""
  364.     entry = readln(cf)
  365.     select
  366.         when upper(entry) = "START" then
  367.         do
  368.             do until upper(subentry) = "END"
  369.                 subentry = readln(cf)
  370.                 select
  371.                     when upper(subword(subentry, 1, 1)) = 'TMPDIR:' then tmpdir = subword(subentry, 2)
  372.                     when upper(subword(subentry, 1, 1)) = 'DESTDIR:' then
  373.                     do
  374.                         destdir = subword(subentry, 2)
  375.  
  376.                         if(upper(destdir) = "GLOBAL") then
  377.                         do
  378.                             address(bbsread)
  379.                             GETGLOBALDATA STEM GLOBALDATA
  380.                             if(rc ~= 0) then
  381.                             do
  382.                                 address(thorport)
  383.                                 REQUESTNOTIFY TEXT '"GETGLOBALDATA:\n'BBSREAD.LASTERROR'"' BT '"_Abort"'
  384.                                 exit(20)
  385.                             end
  386.  
  387.                             destdir = GLOBALDATA.DNLOADPATH
  388.  
  389.                             endchar = right(destdir, 1)
  390.                             if(endchar ~= ":" & endchar ~= "/") then destdir = destdir || '/'
  391.                         end
  392.                     end
  393.  
  394.                     when upper(subword(subentry, 1, 1)) = 'UUDECODER:' then uudecoder = subword(subentry, 2)
  395.                     when upper(subword(subentry, 1, 1)) = 'UUPROGPATH:' then uuprogpath = subword(subentry, 2)
  396.                     when upper(subword(subentry, 1, 1)) = 'FILENOTES:' then if upper(subword(subentry, 2, 1)) = 'YES' then filenotes = 1
  397.                     when upper(subword(subentry, 1, 1)) = 'FILERECOG:' then if upper(subword(subentry, 2, 1)) = 'YES' then filerecog = 1
  398.                     when upper(subword(subentry, 1, 1)) = 'FIRSTTIME:' then if upper(subword(subentry, 2, 1)) = 'YES' then firsttime = 1
  399.                     otherwise nop
  400.                 end
  401.             end
  402.         end
  403.  
  404.         when upper(entry) = "FILETYPE" then
  405.         do
  406.             /* Read filetype configuration */
  407.             filetypecount = filetypecount + 1
  408.             actions = 0
  409.             do until upper(subentry) = "END"
  410.                 subentry = readln(cf)
  411.                 select
  412.                     when upper(subword(subentry, 1, 1)) = 'NAME:' then filetype.filetypecount.name = subword(subentry, 2)
  413.                     when upper(subword(subentry, 1, 1)) = 'EXTENSIONS:' then filetype.filetypecount.ext = upper(subword(subentry, 2))
  414.                     when upper(subword(subentry, 1, 1)) = 'ACTIONNAME:' then
  415.                     do
  416.                         actions = actions + 1
  417.                         filetype.filetypecount.actionname.actions = subword(subentry, 2)
  418.                         subentry = readln(cf)
  419.                         filetype.filetypecount.actioncmdl.actions = subword(subentry, 2)
  420.                     end
  421.                     otherwise nop
  422.                 end
  423.                 filetype.filetypecount.actioncount = actions
  424.             end
  425.         end
  426.  
  427.         when upper(entry) = "UUDECODER" then
  428.         do
  429.             uudecoder.count = uudecoder.count + 1
  430.             uudecoders = uudecoder.count
  431.  
  432.             do until upper(subentry) = "END"
  433.                 subentry = readln(cf)
  434.                 select
  435.                     when upper(subword(subentry, 1, 1)) = 'SHORTNAME:' then uudecoder.uudecoders.shortname = subword(subentry, 2)
  436.                     when upper(subword(subentry, 1, 1)) = 'LONGNAME:' then uudecoder.uudecoders.longname = subword(subentry, 2)
  437.                     when upper(subword(subentry, 1, 1)) = 'COMMANDLINE:' then uudecoder.uudecoders.commandline = subword(subentry, 2)
  438.                     otherwise nop
  439.                 end
  440.             end
  441.         end
  442.  
  443.         otherwise nop
  444.     end
  445. end
  446.  
  447. call close(cf)
  448. return
  449.  
  450. /* Procedure that looks for 'begin xxx filename' lines, in order to extract filenames */
  451.  
  452. FindFileNames: procedure expose cmdlinemode tmpfile msgfilename thorport filenotes filenamecount realfilename.
  453.     if(~cmdlinemode) then
  454.     do
  455.         address(thorport)
  456.         UPDATEPROGRESS REQ progwin PROGRESSTEXT '"Searching for filenames..."'
  457.     end
  458.  
  459.     address command
  460.     "search >" || tmpfile || " " || msgfilename || " begin nonum"
  461.     if(rc ~= 0) then
  462.     do
  463.         address(thorport)
  464.         REQUESTNOTIFY TEXT '"Filenamesearch failed, filenote(s) won''t be added."' BT '"_Ok"'
  465.         filenotes = 0
  466.         break
  467.     end
  468.  
  469.     filenamecount = 1
  470.  
  471.     call open(tmpfh, tmpfile, R)
  472.  
  473.     do until(eof(tmpfh))
  474.         str = readln(tmpfh)
  475.  
  476.         if(left(str, 5) = 'begin') then
  477.         do
  478.             realfilename.filenamecount = substr(str, wordindex(str, 3))
  479.             posi2 = 0
  480.  
  481.             posi = pos(':', realfilename.filenamecount)
  482.             if(posi ~= 0) then posi2 = posi
  483.  
  484.             posi = lastpos('/', realfilename.filenamecount)
  485.             if(posi ~= 0) then posi2 = posi
  486.  
  487.             if(posi2 ~= 0) then realfilename.filenamecount = substr(realfilename.filenamecount, posi2+1)
  488.  
  489.             filenamecount = filenamecount+1
  490.         end
  491.     end
  492.  
  493.     call close(tmpfh)
  494.  
  495.     RETURN
  496.  
  497. /* Procedure for substituting strings inside another string with a string :-) */
  498.  
  499. Substitute: procedure expose thorport
  500.     parse arg str, org, new
  501.     found = index(str, org)
  502.  
  503.     do while found ~= 0
  504.         secondpart = substr(str, found+length(org))
  505.         firstpart = substr(str, 1, length(str) - length(substr(str, found)))
  506.  
  507.         if(org = '%RequestFile' | org = '%RequestDir') then
  508.         do
  509.             if(org = '%RequestFile') then pattern = '#?'
  510.             else pattern = '~#?'
  511.  
  512.             address(thorport)
  513.             REQUESTFILE TITLE '"Select destination:"' ID '"RAM:"' FP PAT '"'pattern'"'
  514.             if(rc ~= 0) then new = "RAM:"
  515.             else new = result
  516.         end
  517.  
  518.         str = firstpart || new || secondpart
  519.         found = index(str, org)
  520.     end
  521.  
  522.     RETURN str
  523.